home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / nrd34.zip / NRD.PAS < prev    next >
Pascal/Delphi Source File  |  1991-05-31  |  71KB  |  2,255 lines

  1. {$I-}
  2. {$V-}
  3. {$M 60000,0,655360}
  4.  
  5. {  ROUTINE:    N R D
  6.  
  7.    PURPOSE:    Control an NRD525 / NRD535 Receiver + database
  8.  
  9.    USAGE:    nrd
  10.  
  11.    AUTHOR:    Tom Whiteside 11505 Oak View, Austin, TX 78759 (512) 258-5924
  12.  
  13.    REVISION:    1.0  04-30-90  TGW  Initial Release
  14.                 1.1  07-07-90  TGW  Serial routines changed to use BIOS for
  15.                                        Windows
  16.                 1.2  07-15-90  TGW  Efficiency tweaks to inc/dec bw/mode
  17.                                     Cursor Highlighting for current line
  18.                                     Cursor tracking data for inc/dec freq
  19.                 1.3  07-29-90  TGW  Remove H(ide from prompt, fix Delete
  20.                                        leaving wrong line highlighted
  21.                                     Added Revision to prompt
  22.                 1.4  09-03-90  TGW  Fixed inc/dec mode past boundary crashing
  23.                                        program; asserted black backgrd on
  24.                                        title and journal
  25.                 1.5  09-29-90  TGW  Added MAP feature
  26.  
  27.                 1.6  11-18-90  TGW  Fixed 2 bugs where cursor got out of
  28.                                     sync with "status line"
  29.                 2.0  12/01-90  TGW  Mods to support other com ports, optional
  30.                                     MAP, help                                 easier for o
  31.                 2.1  12-02-90  TGW  Added time offset to config.dat; fixed
  32.                                     home not putting cursor at top of screen
  33.  
  34.                 2.2  12-25-90  TGW  Added "Com 0" feature to allow using prgm
  35.                                     without serial port...
  36.                 2.3  12-27-90  TGW  Fix to eliminate hang if radio off
  37.  
  38.                 2.4  03-02-91  TGW  Fix for monochrome users (in screen.pas)
  39.                 2.5  03-10-91  TGW  Added Import of Sundstrom data
  40.                 2.6  03-30-91  TGW  Added Active and Inactive log concept
  41.                                     including write from the inactive log
  42.                                     Added "*" command to find radio freq
  43.                                     in database.  Fixed potential hang in
  44.                                     comreadln.  Reduced edit field length
  45.                                     for comments by 1 char.  (Fixed wrap bug
  46.                                     for bottom line)  Removed dangerous Read
  47.                                     command from Journal
  48.                 2.7  04-14-91  TGW  Fixed display bug in inc_freq
  49.                 3.0  04-26-91  TGW  Added NRD535 features
  50.                 3.1  04-27-91  TGW  Fix to journal name select; Added 535
  51.                                     mode to auto-update receiver display
  52.                 3.2  05-12-91  TGW  Added S-meter to 535; changed mode order
  53.                                     to AM -> ECSS_U; added graphics command
  54.                                     for 535; misc bug fixes for 535
  55.  
  56.                 3.3  05-19-91  TGW  Graphics enhancements; commands for time
  57.                                     and spectral displays.  Performance
  58.                                     enhancement to Spectral display
  59.                 3.4  05-31-91  TGW  Misc clean-up to 535 additions mainly to
  60.                                     isolate receiver specific stuff to nrdio.
  61.                                     Fixed minor BWC bug with Spectral plot.
  62.                                     Fixed bug in Import not setting
  63.                                     attenuator.  Fixed bug with Cursor going
  64.                                     below end of file.  Improved key-stroke
  65.                                     performance.  Added date and time stamp
  66.                                     to the status line.  Cleaned up various
  67.                                     bugs in Journal.
  68. }
  69. program nrd(input,output);
  70.  
  71. uses async, crt, dos, graph, screen, nrdio, nrdutil;
  72.  
  73.   procedure program_radio(log_entry:logtype);
  74.  
  75.   { set receiver to log entry; side effect - zaps channel 199 on 535 }
  76.  
  77.   begin
  78.     remote_on;
  79.     if radio_type = 535 then
  80.         with log_entry do
  81.           set_all(199,attenuator,bandwidth,mode,frequency,agc)
  82.     else
  83.       begin
  84.         if map then {force to AM}
  85.           begin
  86.             set_freq(log_entry.frequency + MAP_OFFSET);
  87.             set_mode(AM);
  88.             set_bandwidth(WIDE);
  89.             set_agc(FAST);
  90.           end
  91.         else {use log entry}
  92.           begin
  93.             set_freq(log_entry.frequency);
  94.             if (radio_type = 525) and (log_entry.mode in [ECSS_USB,ECSS_LSB])
  95.                then log_entry.mode:=AM;
  96.             set_mode(log_entry.mode);
  97.             set_bandwidth(log_entry.bandwidth);
  98.             set_agc(log_entry.agc);
  99.           end;
  100.         set_attenuator(log_entry.attenuator);
  101.       end;
  102.     remote_off(REMOTE_DLY);
  103.     update_receiver_display:=TRUE;
  104.   end;
  105.  
  106.   procedure sync_loglist;
  107.   var dummy:boolean;
  108.       i,y_pos:integer;
  109.       recnum:integer;
  110.   begin
  111.     y_pos:=wherey;
  112.     i:=loglist.currentlog;
  113.     loglist.log[i].records:=records;
  114.     recnum:=rec - 1;
  115.     dummy:=precess(recnum,y_pos);
  116.     if recnum = 0 then recnum:=1; { handle special case of empty log }
  117.     loglist.log[i].rec:=recnum;
  118.     put_loglist(loglist);
  119.   end;
  120.  
  121.   procedure do_mark;
  122.   var recnum:integer;
  123.       dummy:boolean;
  124.  
  125.   begin
  126.     x_pos:=wherex; y_pos:=wherey;
  127.     recnum:=rec - 1;
  128.     dummy:=precess(recnum,y_pos);
  129.     if recnum < min_mark then min_mark:=recnum;
  130.     if recnum > max_mark then max_mark:=recnum;
  131.     show_log(rec,TRUE,TRUE);
  132.   end;
  133.  
  134.   procedure do_unmark(display:boolean);
  135.   begin
  136.     x_pos:=wherex; y_pos:=wherey;
  137.     max_mark:=0;
  138.     min_mark:=MAXREC + 1;
  139.     if display then show_log(rec,TRUE,TRUE);
  140.   end;
  141.  
  142.   procedure do_undelete;
  143.   var t,recnum:integer;
  144.       x_pos,y_pos:integer;
  145.       dummy:boolean;
  146.       i,j:integer;
  147.       ch:char;
  148.   begin
  149.     write_prompt('uNdelete:  Type "y" to continue');
  150.     ch:=upcase(fetch);
  151.     cmd_prompt(prompt_num);
  152.     bottom_window;
  153.     if ch <> 'Y' then exit;
  154.     x_pos:=wherex; y_pos:=wherey;
  155.     recnum:=rec - 1;
  156.     dummy:=precess(recnum,y_pos);
  157.     i:=records;
  158.  
  159.     while (i > 1) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  160.       do i:=i - 1;
  161.     if recdata.recstat[recdata.recptr[i]] = DELETED then { found one }
  162.       begin
  163.         t:=recdata.recptr[i];
  164.         recdata.recstat[t]:=SHOW;
  165.         for j:=i downto recnum + 1 do
  166.           recdata.recptr[j]:=recdata.recptr[j - 1];
  167.         recdata.recptr[recnum]:=t;
  168.         put_recdata(loglist.currentlog,recdata);
  169.         show_log(rec,TRUE,TRUE);
  170.       end;
  171.   end;
  172.  
  173.   procedure do_sort(auto:boolean);
  174.   var sortdata:sort_array_type;
  175.       subsortdata:sort_array_type;
  176.       primary,secondary:char;
  177.  
  178.     function get_sort_type(auto:boolean; var primary, secondary:char):boolean;
  179.     begin
  180.       if auto then { automatically do Frequency, Time sort }
  181.         begin
  182.           get_sort_type:=TRUE;
  183.           primary:='F';
  184.           secondary:='T';
  185.           exit;
  186.         end;
  187.       repeat
  188.         write_prompt('Sort - Primary field: D(ate, T(ime, F(req, C(all,'
  189.                      +' L(oc, M(ode, Q(uit');
  190.         primary:=upcase(fetch);
  191.       until primary in ['D','T','F','C','L','M','Q'];
  192.       if primary <> 'Q' then
  193.         repeat
  194.           write_prompt('Sort - Secondary field: D(ate, T(ime, F(req, C(all,'
  195.                      +' L(oc, M(ode, Q(uit');
  196.           secondary:=upcase(fetch);
  197.         until secondary in ['D','T','F','C','L','M','Q'];
  198.       cmd_prompt(prompt_num);
  199.       bottom_window;
  200.       get_sort_type:=(primary <> 'Q') and (secondary <> 'Q');
  201.     end;
  202.  
  203.     procedure get_fields;
  204.     var i:integer;
  205.         logdata:logtype;
  206.  
  207.       procedure init_array(var sortdata:short_str; cmd:char);
  208.       begin
  209.         case cmd of
  210.           'D':sortdata:=copy(logdata.date,1,SHORTSTRLEN);
  211.           'T':sortdata:=copy(logdata.begin_time,1,SHORTSTRLEN);
  212.           'F':str(logdata.frequency:8:1,sortdata);
  213.           'C':sortdata:=copy(logdata.callsign,1,SHORTSTRLEN);
  214.           'L':sortdata:=copy(logdata.location,1,SHORTSTRLEN);
  215.           'M':case logdata.mode of
  216.                 RTTY:sortdata:='RTTY';
  217.                 CW  :sortdata:='CW';
  218.                 USB :sortdata:='USB';
  219.                 LSB :sortdata:='LSB';
  220.                 AM  :sortdata:='AM';
  221.                 FM  :sortdata:='FM';
  222.                 FAX :sortdata:='FAX';
  223.                end;
  224.         end;
  225.       end;
  226.  
  227.     begin
  228.       home;
  229.       for i:=1 to records do
  230.       begin
  231.         if recdata.recstat[i] = DELETED then { dummy sort pos }
  232.           begin
  233.             sortdata[i]:=chr(255);
  234.             subsortdata[i]:=chr(255);
  235.           end
  236.         else
  237.           begin
  238.             get_log(logbuf,logdata,i);
  239.             init_array(sortdata[i],primary);
  240.             init_array(subsortdata[i],secondary);
  241.           end;
  242.         recdata.recptr[i]:=i;
  243.       end;
  244.     end;
  245.  
  246.     procedure primary_sort; { sort on primary field }
  247.     begin
  248.       write(output,'Primary sort');
  249.       sort(sortdata,recdata.recptr,1,records);
  250.     end;
  251.  
  252.     procedure secondary_sort; { sort on secondary field }
  253.     var i,top:integer;
  254.         tempstr:string;
  255.     begin
  256.       top:=1; home;
  257.       write(output,'Secondary sort');
  258.       while (top < records) do
  259.         begin
  260.           i:=0;
  261.           tempstr:=sortdata[top];
  262.           while (top + i < records) and (tempstr = sortdata[top + i]) do
  263.             begin
  264.               sortdata[top + i]:=subsortdata[recdata.recptr[top + i]];
  265.               inc(i);
  266.             end;
  267.           sort(sortdata,recdata.recptr,top,i);
  268.           top:=top + i;
  269.         end;
  270.     end;
  271.  
  272.   begin
  273.     if get_sort_type(auto,primary,secondary) then
  274.       begin
  275.         get_fields;
  276.         primary_sort;
  277.         secondary_sort;
  278.       end;
  279.     show_log(rec,TRUE,TRUE);
  280.     put_recdata(loglist.currentlog,recdata);
  281.   end;
  282.  
  283.   function upcasestr(s:string):string;
  284.   var i:integer;
  285.       s1:string;
  286.   begin
  287.     s1:=s;
  288.     for i:=1 to length(s) do s1[i]:=upcase(s[i]);
  289.     upcasestr:=s1;
  290.   end;
  291.  
  292.   procedure do_page;
  293.   begin
  294.     x_pos:=wherex; y_pos:=wherey;
  295.     display_page:=display_page + 1;
  296.     if display_page > 3 then display_page:=1;
  297.     draw_display_titles;
  298.     bottom_window;
  299.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  300.   end;
  301.  
  302.   procedure do_tab;
  303.   begin
  304.     x_pos:=wherex; y_pos:=wherey;
  305.     case display_page of
  306.       1:begin
  307.           if x_pos in [1..5]   then x_pos:=6  else
  308.           if x_pos in [6..12]  then x_pos:=13 else
  309.           if x_pos in [13..17] then x_pos:=18 else
  310.           if x_pos in [18..22] then x_pos:=23 else
  311.           if x_pos in [23..31] then x_pos:=32 else
  312.           if x_pos in [32..51] then x_pos:=52 else
  313.             begin
  314.               x_pos:=11;
  315.               gotoxy(x_pos,y_pos);
  316.               do_page;
  317.             end;
  318.           gotoxy(x_pos,y_pos);
  319.         end;
  320.       2:begin
  321.           x_pos:=32;
  322.           gotoxy(x_pos,y_pos);
  323.           do_page;
  324.         end;
  325.       3:begin
  326.           if x_pos in [1..5]   then x_pos:=6  else
  327.           if x_pos in [6..12]  then x_pos:=13 else
  328.           if x_pos in [13..17] then x_pos:=18 else
  329.           if x_pos in [18..22] then x_pos:=23 else
  330.           if x_pos in [23..31] then x_pos:=32 else
  331.           if x_pos in [32..36] then x_pos:=37 else
  332.           if x_pos in [37..42] then x_pos:=43 else
  333.           if x_pos in [43..48] then x_pos:=49 else
  334.             begin
  335.               x_pos:=6;
  336.               gotoxy(x_pos,y_pos);
  337.               do_page;
  338.             end;
  339.           gotoxy(x_pos,y_pos);
  340.         end;
  341.     end;
  342.   end;
  343.  
  344.   procedure do_backtab;
  345.   begin
  346.     x_pos:=wherex; y_pos:=wherey;
  347.     case display_page of
  348.       1:begin
  349.           if x_pos in [7..13]  then x_pos:=6  else
  350.           if x_pos in [14..18] then x_pos:=13 else
  351.           if x_pos in [19..23] then x_pos:=18 else
  352.           if x_pos in [24..32] then x_pos:=23 else
  353.           if x_pos in [33..80] then x_pos:=32 else
  354.             begin
  355.               x_pos:=38;
  356.               gotoxy(x_pos,y_pos);
  357.               display_page:=display_page - 2;
  358.               do_page;
  359.             end;
  360.           gotoxy(x_pos,y_pos);
  361.         end;
  362.       2:begin
  363.           if x_pos in [3..10]  then x_pos:=2  else
  364.           if x_pos in [12..80] then x_pos:=11 else
  365.             begin
  366.               x_pos:=52;
  367.               gotoxy(x_pos,y_pos);
  368.               display_page:=display_page - 2;
  369.               do_page;
  370.             end;
  371.           gotoxy(x_pos,y_pos);
  372.         end;
  373.       3:begin
  374.           if x_pos in [7..13]  then x_pos:=6  else
  375.           if x_pos in [14..18] then x_pos:=13 else
  376.           if x_pos in [19..23] then x_pos:=18 else
  377.           if x_pos in [24..32] then x_pos:=23 else
  378.           if x_pos in [33..37] then x_pos:=32 else
  379.           if x_pos in [38..43] then x_pos:=37 else
  380.           if x_pos in [44..49] then x_pos:=43 else
  381.           if x_pos in [50..80] then x_pos:=49 else
  382.             begin
  383.               x_pos:=11;
  384.               gotoxy(x_pos,y_pos);
  385.               display_page:=display_page - 2;
  386.               do_page;
  387.             end;
  388.           gotoxy(x_pos,y_pos);
  389.         end;
  390.     end;
  391.   end;
  392.  
  393.   procedure do_edit; { edit field cursor is on }
  394.   var recnum:integer;
  395.       logdata:logtype;
  396.       s:string;
  397.       i,j,y,dummy:integer;
  398.       tabkey,backtabkey:boolean;
  399.  
  400.     procedure edit_page1;
  401.     begin
  402.       case x_pos of
  403.          6..12: editfield(5, y,DATELEN,FALSE,tabkey,backtabkey,logdata.date);
  404.         13..17: begin
  405.                   editfield(12,y,TIMELEN,FALSE,tabkey,backtabkey
  406.                                 ,logdata.begin_time);
  407.                   while length(logdata.begin_time) < 4 do
  408.                       logdata.begin_time:=concat('0',logdata.begin_time);
  409.                 end;
  410.         18..22: begin
  411.                   editfield(17,y,TIMELEN,FALSE,tabkey,backtabkey
  412.                                 ,logdata.end_time);
  413.                   while length(logdata.end_time) < 4 do
  414.                       logdata.end_time:=concat('0',logdata.end_time);
  415.                 end;
  416.         23..31: begin
  417.                   str(logdata.frequency:8:2,s);
  418.                   editfield(22,y,8,TRUE,tabkey,backtabkey,s);
  419.                   val(s,logdata.frequency,dummy);
  420.                 end;
  421.         32..51: editfield(31,y,CALLSIGNLEN,FALSE,tabkey,backtabkey
  422.                               ,logdata.callsign);
  423.         52..80: editfield(51,y,LOCATIONLEN,FALSE,tabkey,backtabkey
  424.                               ,logdata.location);
  425.       end;
  426.     end;
  427.  
  428.     procedure edit_page2;
  429.     begin
  430.       case x_pos of
  431.          1..10: begin
  432.                   str(logdata.frequency:8:2,s);
  433.                   editfield(1,y,8,TRUE,tabkey,backtabkey,s);
  434.                   val(s,logdata.frequency,dummy);
  435.                 end;
  436.         11..80: editfield(10,y,COMMENTLEN-1,FALSE,tabkey,backtabkey
  437.                               ,logdata.comment);
  438.       end;
  439.     end;
  440.  
  441.     procedure edit_page3;
  442.     begin
  443.       case x_pos of
  444.          6..12: editfield(5, y,DATELEN,FALSE,tabkey,backtabkey,logdata.date);
  445.         13..17: begin
  446.                   editfield(12,y,TIMELEN,FALSE,tabkey,backtabkey
  447.                                 ,logdata.begin_time);
  448.                   while length(logdata.begin_time) < 4 do
  449.                       logdata.begin_time:=concat('0',logdata.begin_time);
  450.                 end;
  451.         18..22: begin
  452.                   editfield(17,y,TIMELEN,FALSE,tabkey,backtabkey
  453.                                 ,logdata.end_time);
  454.                   while length(logdata.end_time) < 4 do
  455.                       logdata.end_time:=concat('0',logdata.end_time);
  456.                 end;
  457.         23..31: begin
  458.                   str(logdata.frequency:8:2,s);
  459.                   editfield(22,y,8,TRUE,tabkey,backtabkey,s);
  460.                   val(s,logdata.frequency,dummy);
  461.                 end;
  462.         32..36: begin
  463.                   case logdata.mode of
  464.                     RTTY: s:='RTTY';
  465.                     CW:   s:=' CW';
  466.                     USB:  s:='USB';
  467.                     LSB:  s:='LSB';
  468.                     AM:   s:=' AM';
  469.                     FM:   s:=' FM';
  470.                     FAX:  s:='FAX';
  471.                   end;
  472.                   editfield(31,y,4,FALSE,tabkey,backtabkey,s);
  473.                   s:=upcasestr(s);
  474.                   if pos('RTTY',s) > 0 then logdata.mode:=RTTY else
  475.                   if pos('CW',s)   > 0 then logdata.mode:=CW   else
  476.                   if pos('USB',s)  > 0 then logdata.mode:=USB  else
  477.                   if pos('LSB',s)  > 0 then logdata.mode:=LSB  else
  478.                   if pos('AM',s)   > 0 then logdata.mode:=AM   else
  479.                   if pos('FM',s)   > 0 then logdata.mode:=FM   else
  480.                   if pos('FAX',s)  > 0 then logdata.mode:=FAX
  481.                 end;
  482.         37..42: begin
  483.                   case logdata.bandwidth of
  484.                     NARR: s:=' NARR';
  485.                     INTER:s:='INTER';
  486.                     WIDE: s:=' WIDE';
  487.                     AUX:  s:=' AUX';
  488.                   end;
  489.                   editfield(36,y,5,FALSE,tabkey,backtabkey,s);
  490.                   s:=upcasestr(s);
  491.                   if pos('INTER',s) > 0 then logdata.bandwidth:=INTER else
  492.                   if pos('NARR',s)  > 0 then logdata.bandwidth:=NARR  else
  493.                   if pos('WIDE',s)  > 0 then logdata.bandwidth:=WIDE  else
  494.                   if pos('AUX' ,s)  > 0 then logdata.bandwidth:=AUX
  495.                 end;
  496.         43..48: begin
  497.                   case logdata.agc of
  498.                     FAST: s:='FAST';
  499.                     SLOW: s:='SLOW';
  500.                     OFF:  s:=' OFF';
  501.                   end;
  502.                   editfield(42,y,4,FALSE,tabkey,backtabkey,s);
  503.                   s:=upcasestr(s);
  504.                   if pos('FAST',s) > 0 then logdata.agc:=FAST else
  505.                   if pos('SLOW',s) > 0 then logdata.agc:=SLOW else
  506.                   if pos('OFF',s)  > 0 then logdata.agc:=OFF
  507.                 end;
  508.         49..51: begin
  509.                   case logdata.attenuator of
  510.                     YES: s:='ON';
  511.                     NO:  s:='OFF';
  512.                   end;
  513.                   editfield(48,y,3,FALSE,tabkey,backtabkey,s);
  514.                   s:=upcasestr(s);
  515.                   if pos('OFF',s) > 0 then logdata.attenuator:=NO else
  516.                   if pos('ON',s)  > 0 then logdata.attenuator:=YES
  517.                 end;
  518.       end;
  519.     end;
  520.  
  521.   begin { do_edit }
  522.     x_pos:=wherex; y_pos:=wherey; y:=y_pos - 1;
  523.     recnum:=rec - 1;
  524.     if precess(recnum,y_pos) then
  525.       begin
  526.         get_log(logbuf,logdata,recdata.recptr[recnum]);
  527.         case display_page of
  528.           1: edit_page1;
  529.           2: edit_page2;
  530.           3: edit_page3;
  531.         end;
  532.         put_log(logbuf,logdata,recdata.recptr[recnum]);
  533.         if not (tabkey or backtabkey) then
  534.           begin
  535.             gotoxy(x_pos,y_pos);
  536.             show_log(rec,TRUE,TRUE);
  537.           end;
  538.       end;
  539.     gotoxy(x_pos,y_pos);
  540.     if tabkey then
  541.       begin
  542.         do_tab;
  543.         do_edit;
  544.       end
  545.     else if backtabkey then
  546.       begin
  547.         do_backtab;
  548.         do_edit;
  549.       end;
  550.   end;
  551.  
  552.   procedure do_delete;
  553.   var x_pos,y_pos:integer;
  554.       recnum:integer;
  555.       ch:char;
  556.       i,t:integer;
  557.   begin
  558.     x_pos:=wherex; y_pos:=wherey;
  559.     recnum:=rec - 1;
  560.     write_prompt('Delete:  Type "y" to continue');
  561.     ch:=upcase(fetch);
  562.     cmd_prompt(prompt_num);
  563.     bottom_window;
  564.     if ch = 'Y' then if precess(recnum,y_pos) then
  565.       begin
  566.         t:=recdata.recptr[recnum];
  567.         recdata.recstat[t]:=DELETED;
  568.         for i:=recnum to records - 1 do with recdata do
  569.           recptr[i]:=recptr[i + 1];
  570.         recdata.recptr[records]:=t;
  571.         show_log(rec,TRUE,TRUE);
  572.         put_recdata(loglist.currentlog,recdata);
  573.       end;
  574.   end;
  575.  
  576.   procedure do_log;
  577.   var x_pos,y_pos:integer;
  578.       t,recnum:integer;
  579.       ch:char;
  580.       i,j:integer;
  581.       dummy:boolean;
  582.       logdata:logtype;
  583.   begin
  584.     x_pos:=32; y_pos:=wherey;
  585.     recnum:=rec - 1;
  586.     dummy:=precess(recnum,y_pos);
  587.     { get receiver status }
  588.     if radio_type = 525 then remote_on else toggle_remote;
  589.     show_receiver;
  590.     remote_off(0);
  591.     i:=1;
  592.     while (i < records) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  593.        do inc(i);
  594.     if (i >= records) and (recdata.recstat[recdata.recptr[i]]<>DELETED) then
  595.       { insert new entry here }
  596.       begin
  597.         inc(records);
  598.         i:=records;
  599.         recdata.recptr[i]:=i;
  600.         loglist.log[loglist.currentlog].records:=records;
  601.         put_loglist(loglist);
  602.       end;
  603.     t:=recdata.recptr[i];
  604.     if recnum = 0 then recnum:=1; { special case for new arrays }
  605.     for j:=i downto recnum + 1 do with recdata do
  606.       recptr[j]:=recptr[j - 1];
  607.     recdata.recptr[recnum]:=t;
  608.     recdata.recstat[t]:=SHOW;
  609.     clear_log(logdata);
  610.     with receiverstat do
  611.       begin
  612.         if map then {center frequency}
  613.           begin
  614.             logdata.frequency:=trunc(frequency/5.0 + 0.5) * 5;
  615.             logdata.mode:=USB;
  616.             logdata.bandwidth:=INTER;
  617.           end
  618.         else
  619.           begin
  620.             logdata.frequency:=frequency;
  621.             logdata.mode:=mode;
  622.             logdata.bandwidth:=bandwidth;
  623.           end;
  624.         logdata.agc:=agc;
  625.         logdata.attenuator:=attenuator;
  626.       end;
  627.     put_log(logbuf,logdata,recdata.recptr[recnum]);
  628.     put_recdata(loglist.currentlog,recdata);
  629.     if display_page <> 1 then
  630.       begin
  631.         display_page:=1;
  632.         draw_display_titles;
  633.         bottom_window;
  634.       end;
  635.     gotoxy(x_pos,y_pos);
  636.     show_log(rec,TRUE,TRUE);
  637.     do_edit;
  638.   end;
  639.  
  640.   procedure do_tune;
  641.  
  642.   { assign log entry at cursor location to radio }
  643.  
  644.   var recnum:integer;
  645.       logdata:logtype;
  646.   begin
  647.    y_pos:=wherey;
  648.    recnum:=rec - 1;
  649.    if precess(recnum, y_pos) then
  650.      begin
  651.        get_log(logbuf,logdata,recdata.recptr[recnum]);
  652.        program_radio(logdata);
  653.        if radio_type = 535 then toggle_remote;
  654.      end;
  655.   end;
  656.  
  657.   function find_rec(rec:integer; freq:real):integer; { find record >= frequency }
  658.   var j:integer;
  659.       logdata:logtype;
  660.       first_try, found:boolean;
  661.   begin
  662.     j:=rec - 20; { skip back enuf records to find start hopefully }
  663.     if j < 0 then j:=0;
  664.     found:=FALSE; first_try:=TRUE;
  665.     while (j < records) and not found do
  666.       begin
  667.         if precess(j,1) then
  668.           begin
  669.             get_log(logbuf,logdata,recdata.recptr[j]);
  670.             if first_try and (logdata.frequency > freq)
  671.               then j:=0
  672.               else found:=logdata.frequency >= freq;
  673.             first_try:=FALSE;
  674.           end;
  675.       end;
  676.     find_rec:=j;
  677.   end;
  678.  
  679.   procedure inc_freq;
  680.   var s:string;
  681.       x_pos,y_pos,i:integer;
  682.       orig_freq:real;
  683.  
  684.     procedure display(frequency:real); { find displayed line matching freq }
  685.     var found,lt:boolean;
  686.         j:integer;
  687.     begin
  688.       j:=0; found:=FALSE; lt:=FALSE;
  689.       while (j < LINES - REC_WIN_Y_BOTTOM - 1) and not found do
  690.         begin
  691.           inc(j);
  692.           if frequency > displayed_freq[j] then lt:=TRUE; {condition for fnd}
  693.           found:=frequency <= displayed_freq[j];
  694.         end;
  695.       if found and lt then { found it and its on the screen }
  696.         begin
  697.           y_pos:=j;
  698.           gotoxy(x_pos,y_pos);
  699.           show_log(rec,FALSE,TRUE);
  700.         end
  701.       else { new screen }
  702.         begin
  703.           rec:=find_rec(rec, frequency);
  704.           gotoxy(x_pos,1);
  705.           show_log(rec,TRUE,TRUE);
  706.         end;
  707.     end;
  708.  
  709.   begin {inc_freq}
  710.     x_pos:=wherex; y_pos:=wherey;
  711.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  712.     with receiverstat do
  713.       begin
  714.         remote_on;
  715.         orig_freq:=frequency;
  716.         frequency:=trunc(frequency/10.0) * 10.0;
  717.         if orig_freq - frequency >= 5.0 then frequency:=frequency + 5.0;
  718.         case mode of
  719.           USB: set_freq(frequency + 4.0);
  720.           LSB: set_freq(frequency + 6.0);
  721.           AM:
  722.           else
  723.             begin
  724.               for i:=1 to 4 do
  725.                 begin
  726.                   set_freq(frequency + i);
  727.                   delay(150);
  728.                 end;
  729.             end;
  730.         end;
  731.         delay(200);
  732.         frequency:=frequency + 5.0;
  733.         if map then frequency:=frequency + MAP_OFFSET;
  734.         set_freq(frequency);
  735.         remote_off(0);
  736.         if radio_type = 535 then toggle_remote;
  737.         show_receiver;
  738.         display(frequency);
  739.       end;
  740.   end;
  741.  
  742.   procedure dec_freq;
  743.   var s:string;
  744.       x_pos,y_pos,i:integer;
  745.       orig_freq:real;
  746.  
  747.     procedure display(frequency:real); { find displayed line matching freq }
  748.     var found,lt:boolean;
  749.         j:integer;
  750.     begin
  751.       j:=LINES - REC_WIN_Y_BOTTOM; found:=FALSE; lt:=FALSE;
  752.       while (j > 1) and not found do
  753.         begin
  754.           dec(j);
  755.           if frequency < displayed_freq[j] then lt:=TRUE;{condition for fnd}
  756.           found:=frequency >= displayed_freq[j];
  757.         end;
  758.       if found and lt then { found it and its on the screen }
  759.         begin
  760.           gotoxy(x_pos,j);
  761.           show_log(rec,FALSE,TRUE);
  762.         end
  763.       else { new screen }
  764.         begin
  765.           rec:=find_rec(rec, frequency);
  766.           rec:=rec - LINES + REC_WIN_Y_BOTTOM + 2;
  767.           if rec < 1 then rec:=1;
  768.           gotoxy(x_pos,1);
  769.           show_log(rec,TRUE,TRUE);
  770.           show_log(rec,FALSE,FALSE);
  771.           y_pos:=0; found:=FALSE;
  772.           while not found and (y_pos < LINES - REC_WIN_Y_BOTTOM - 1) do
  773.             begin
  774.               inc(y_pos);
  775.               found:=displayed_freq[y_pos] >=frequency;
  776.             end;
  777.           gotoxy(x_pos,y_pos);
  778.           show_log(rec,FALSE,TRUE);
  779.         end;
  780.     end;
  781.  
  782.   begin {dec_freq}
  783.     x_pos:=wherex; y_pos:=wherey;
  784.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  785.     with receiverstat do
  786.       begin
  787.         remote_on;
  788.         orig_freq:=frequency;
  789.         frequency:=trunc(frequency/10.0) * 10.0;
  790.         if orig_freq - frequency > 5.0 then frequency:=frequency + 10.0
  791.         else if orig_freq - frequency > 0.0 then frequency:=frequency + 5.0;
  792.         case mode of
  793.           USB: set_freq(frequency - 6.0);
  794.           LSB: set_freq(frequency - 4.0);
  795.           AM:
  796.           else
  797.             begin
  798.               for i:=1 to 4 do
  799.                 begin
  800.                   set_freq(frequency - i);
  801.                   delay(150);
  802.                 end;
  803.             end;
  804.         end;
  805.         delay(200);
  806.         frequency:=frequency - 5.0;
  807.         if map then frequency:= frequency + MAP_OFFSET;
  808.         set_freq(frequency);
  809.         remote_off(0);
  810.         if radio_type = 535 then toggle_remote;
  811.         show_receiver;
  812.         display(receiverstat.frequency);
  813.       end;
  814.   end;
  815.  
  816.   procedure find_freq;
  817.   var s:string;
  818.       x_pos,y_pos,i:integer;
  819.       orig_freq:real;
  820.       ch:char;
  821.  
  822.     procedure display(frequency:real); { find displayed line matching freq }
  823.     var found:boolean;
  824.     begin
  825.       rec:=find_rec(1, frequency);
  826.       rec:=rec - LINES + REC_WIN_Y_BOTTOM + 2;
  827.       if rec < 1 then rec:=1;
  828.       gotoxy(x_pos,1);
  829.       show_log(rec,TRUE,TRUE);
  830.       show_log(rec,FALSE,FALSE);
  831.       y_pos:=0; found:=FALSE;
  832.       while not found and (y_pos < LINES - REC_WIN_Y_BOTTOM - 1) do
  833.         begin
  834.           inc(y_pos);
  835.           found:=displayed_freq[y_pos] >=frequency;
  836.         end;
  837.       gotoxy(x_pos,y_pos);
  838.       show_log(rec,FALSE,TRUE);
  839.     end;
  840.  
  841.   begin {find_freq}
  842.     x_pos:=wherex; y_pos:=wherey;
  843.     show_log(rec,FALSE,FALSE); { unhighlight current cursor line }
  844.     with receiverstat do
  845.       begin
  846.         if radio_type = 525 then remote_on
  847.         else toggle_remote;
  848.         remote_off(0);
  849.         show_receiver;
  850.         display(receiverstat.frequency);
  851.       end;
  852.   end;
  853.  
  854.   procedure do_kiwa; { different mode if KIWA MAP unit in use }
  855.   var freq,offset:real;
  856.       x_pos,y_pos:integer;
  857.   begin
  858.     x_pos:=wherex; y_pos:=wherey;
  859.     map:=not map; {toggle mode}
  860.     with receiverstat do
  861.       begin
  862.         if map then {enable mode}
  863.           begin
  864.             if mode = USB then offset:=MAP_OFFSET else offset:=-MAP_OFFSET;
  865.             remote_on;
  866.             set_mode(AM);
  867.             mode:=AM;
  868.             set_bandwidth(WIDE);
  869.             bandwidth:=WIDE;
  870.             set_agc(FAST);
  871.             agc:=FAST;
  872.             frequency:=trunc(frequency / 5.0 + 0.5) * 5.0 + offset;
  873.             set_freq(frequency);
  874.             remote_off(REMOTE_DLY);
  875.           end
  876.         else
  877.           begin
  878.             remote_on;
  879.             freq:=frequency;
  880.             frequency:=trunc(frequency / 5.0 + 0.5) * 5.0;
  881.             set_freq(frequency);
  882.             if frequency < freq then
  883.               begin
  884.                 set_mode(USB);
  885.                 mode:=USB;
  886.               end
  887.             else
  888.               begin
  889.                 set_mode(LSB);
  890.                 mode:=LSB;
  891.               end;
  892.             set_bandwidth(INTER);
  893.             bandwidth:=INTER;
  894.           end;
  895.         remote_off(REMOTE_DLY);
  896.       end;
  897.     show_receiver;
  898.     gotoxy(x_pos,y_pos);
  899.   end;
  900.  
  901.   procedure do_confirm;
  902.  
  903.   { refresh database time and date and receiver status }
  904.  
  905.   var recnum:integer;
  906.       tlog,logdata:logtype;
  907.       t_begin, t_end, t_now, dummy:integer;
  908.       ch:char;
  909.       s:string;
  910.   begin
  911.    x_pos:=wherex; y_pos:=wherey;
  912.    { get receiver status }
  913.    if radio_type = 525 then remote_on
  914.    else
  915.      begin
  916.        toggle_remote;
  917.        if async_buffer_check(ch) then check_status(s);
  918.      end;
  919.    show_receiver;
  920.    remote_off(0);
  921.    recnum:=rec - 1;
  922.    if precess(recnum, y_pos) then
  923.      begin
  924.       clear_log(tlog);
  925.       get_log(logbuf,logdata,recdata.recptr[recnum]);
  926.       write_prompt('Confirm:  Type "y" to continue');
  927.       ch:=upcase(fetch);
  928.       cmd_prompt(prompt_num);
  929.       if ch = 'Y' then
  930.         begin
  931.           logdata.date:=tlog.date;
  932.           val(tlog.begin_time,t_now,dummy);
  933.           val(logdata.begin_time,t_begin,dummy);
  934.           val(logdata.end_time,t_end,dummy);
  935.           t_begin:=t_begin - t_now;
  936.           if t_begin < 0 then t_begin:=t_begin + 2400;
  937.           t_end:=t_now - t_end;
  938.           if t_end < 0 then t_end:=t_end + 2400;
  939.           if t_begin < t_end
  940.              then if t_begin < 1200 then logdata.begin_time:=tlog.begin_time;
  941.           if t_end < t_begin
  942.              then if t_end < 1200 then logdata.end_time:=tlog.begin_time;
  943.           with receiverstat do
  944.             begin
  945.               if not map then {don't update receiver params if using map}
  946.                 begin
  947.                   logdata.frequency:=frequency;
  948.                   logdata.mode:=mode;
  949.                   logdata.agc:=agc;
  950.                   logdata.attenuator:=attenuator;
  951.                   logdata.bandwidth:=bandwidth;
  952.                 end;
  953.             end;
  954.           put_log(logbuf,logdata,recdata.recptr[recnum]);
  955.         end;
  956.       end;
  957.    bottom_window;
  958.    show_log(rec,TRUE,TRUE);
  959.   end;
  960.  
  961.   procedure do_write; { as in dudley... }
  962.   { copy record at cursor in inactive log to current log }
  963.   var x_pos,y_pos:integer;
  964.       t,recnum:integer;
  965.       ch:char;
  966.       i,j:integer;
  967.       dummy:boolean;
  968.   begin
  969.     if last_log = 0 then exit;
  970.     x_pos:=wherex; y_pos:=wherey;
  971.     recnum:=rec - 1;
  972.     dummy:=precess(recnum,y_pos);
  973.     i:=1;
  974.     while (i < records) and (recdata.recstat[recdata.recptr[i]] <> DELETED)
  975.        do inc(i);
  976.     if (i >= records) and (recdata.recstat[recdata.recptr[i]]<>DELETED) then
  977.       { insert new entry here }
  978.       begin
  979.         inc(records);
  980.         i:=records;
  981.         recdata.recptr[i]:=i;
  982.         loglist.log[loglist.currentlog].records:=records;
  983.         put_loglist(loglist);
  984.       end;
  985.     t:=recdata.recptr[i];
  986.     if recnum = 0 then recnum:=1; { special case for new arrays }
  987.     for j:=i downto recnum + 1 do with recdata do
  988.       recptr[j]:=recptr[j - 1];
  989.     recdata.recptr[recnum]:=t;
  990.     recdata.recstat[t]:=SHOW;
  991.     put_log(logbuf,last_log_data,recdata.recptr[recnum]);
  992.     put_recdata(loglist.currentlog,recdata);
  993.     if display_page <> 1 then
  994.       begin
  995.         display_page:=1;
  996.         draw_display_titles;
  997.         bottom_window;
  998.       end;
  999.     gotoxy(x_pos,y_pos);
  1000.     show_log(rec,TRUE,TRUE);
  1001.   end;
  1002.  
  1003.   procedure do_pageup(cnt:byte);
  1004.   var i,j:integer;
  1005.       dummy:boolean;
  1006.       last:boolean;
  1007.   begin
  1008.     x_pos:=wherex;
  1009.     for j:=1 to cnt do
  1010.       begin
  1011.         for i:=1 to LINES - REC_WIN_Y_BOTTOM + 1 do
  1012.           begin
  1013.             if rec > 1 then dec(rec);
  1014.             while (rec > 1) and (recdata.recstat[recdata.recptr[rec]]
  1015.                     <> SHOW) do dec(rec);
  1016.           end;
  1017.       end;
  1018.  
  1019.     { place cursor at bottom (or last record) }
  1020.     y_pos:=0;
  1021.     j:=rec - 1;
  1022.     last:=FALSE;
  1023.     for i:=2 to LINES - REC_WIN_Y_BOTTOM  do
  1024.       begin
  1025.         dummy:=precess(j,1);
  1026.         if (recdata.recstat[recdata.recptr[j]] = SHOW) and (not last)
  1027.            then inc(y_pos);
  1028.         last:=j = records; { funky ending condition; j won't exceed records}
  1029.       end;
  1030.     gotoxy(x_pos,y_pos);
  1031.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  1032.   end;
  1033.  
  1034.   procedure do_pagedown(cnt:byte);
  1035.   var i:integer;
  1036.       dummy:boolean;
  1037.   begin
  1038.     x_pos:=wherex; y_pos:=1;
  1039.     gotoxy(x_pos,y_pos);
  1040.     for i:=1 to cnt do
  1041.       begin
  1042.         dummy:= precess(rec, LINES - REC_WIN_Y_BOTTOM - 1);
  1043.         if rec >= records then
  1044.           begin
  1045.              rec:=records;
  1046.              if rec < 1 then rec:=1; { special case for empty file }
  1047.              while (recdata.recstat[recdata.recptr[rec]] <> SHOW) do
  1048.                dec(rec);
  1049.           end;
  1050.       end;
  1051.     if rslt = 0 then show_log(rec,TRUE,TRUE);
  1052.   end;
  1053.  
  1054.   procedure do_up;
  1055.   begin
  1056.     x_pos:=wherex; y_pos:=wherey;
  1057.     y_pos:=y_pos - 1;
  1058.     if y_pos < 1 then
  1059.       begin
  1060.         y_pos:=1;
  1061.         if rec > 1 then rec:=rec - 1;
  1062.         show_log(rec,TRUE,TRUE);
  1063.       end
  1064.     else
  1065.       begin
  1066.         show_log(rec,FALSE,FALSE);
  1067.         gotoxy(x_pos,y_pos);
  1068.         show_log(rec,FALSE,TRUE);
  1069.       end;
  1070.   end;
  1071.  
  1072.   procedure do_down;
  1073.   var dummy:boolean;
  1074.       i,y,j:integer;
  1075.   begin
  1076.     x_pos:=wherex; y:=wherey;
  1077.     inc(y);
  1078.  
  1079.     { keep cursor from moving past bottom }
  1080.     j:=rec - 1;
  1081.     for i:=1 to y do
  1082.       begin
  1083.         inc(j);
  1084.         if (j > records) or (recdata.recstat[recdata.recptr[j]]<>SHOW) then
  1085.           begin
  1086.             y_pos:=wherey;
  1087.             exit;
  1088.           end;
  1089.       end;
  1090.     y_pos:=y;
  1091.     if y_pos > LINES - REC_WIN_Y_BOTTOM - 1 then
  1092.      begin
  1093.        y_pos:=LINES - REC_WIN_Y_BOTTOM - 1;
  1094.        dummy:=precess(rec,1);
  1095.        if rec > records then rec:=records;
  1096.        if rslt = 0 then show_log(rec,TRUE,TRUE);
  1097.      end
  1098.     else
  1099.       begin
  1100.         show_log(rec,FALSE,FALSE);
  1101.         gotoxy(x_pos,y_pos);
  1102.         show_log(rec,FALSE,TRUE);
  1103.       end;
  1104.   end;
  1105.  
  1106.   procedure do_right;
  1107.   begin
  1108.     x_pos:=wherex; y_pos:=wherey;
  1109.     inc(x_pos);
  1110.     if x_pos > CHARPERLINE then
  1111.       begin
  1112.         x_pos:=1;
  1113.         inc(display_page);
  1114.         if display_page > 3 then display_page:=1;
  1115.         draw_display_titles;
  1116.         bottom_window;
  1117.         if rslt = 0 then show_log(rec,TRUE,TRUE);
  1118.       end;
  1119.     gotoxy(x_pos,y_pos);
  1120.   end;
  1121.  
  1122.   procedure do_left;
  1123.   begin
  1124.     x_pos:=wherex; y_pos:=wherey;
  1125.     x_pos:=x_pos - 1;
  1126.     if x_pos < 1 then
  1127.       begin
  1128.         x_pos:=CHARPERLINE;
  1129.         display_page:=display_page - 1;
  1130.         if display_page < 1 then display_page:=3;
  1131.         draw_display_titles;
  1132.         bottom_window;
  1133.         if rslt = 0 then show_log(rec,TRUE,TRUE);
  1134.       end;
  1135.     gotoxy(x_pos,y_pos);
  1136.   end;
  1137.  
  1138.   procedure do_home;
  1139.   begin
  1140.     rec:=1; x_pos:=1; y_pos:=1;
  1141.     gotoxy(x_pos,y_pos);
  1142.     show_log(rec,TRUE,TRUE);
  1143.   end;
  1144.  
  1145.   procedure do_end;
  1146.   begin
  1147.     rec:=records; x_pos:=1; y_pos:=1;
  1148.     do_pagedown(1);
  1149.   end;
  1150.  
  1151.   procedure new_log(lognum:byte; var rslt:integer);
  1152.   begin
  1153.     open_log(logbuf,lognum, rslt);
  1154.     get_recdata(lognum, recdata);
  1155.     records:=loglist.log[lognum].records;
  1156.     rec:=loglist.log[lognum].rec;
  1157.   end;
  1158.  
  1159.   procedure do_alternate;
  1160.   var i:integer;
  1161.       recnum:integer;
  1162.       t_begin, t_end, t_now, dummy:integer;
  1163.   begin
  1164.     x_pos:=wherex; y_pos:=wherey;
  1165.     recnum:=rec - 1;
  1166.     sync_loglist;
  1167.     if loglist.currentlog > 0 then { window current rec for "W" command }
  1168.       begin
  1169.         new_log(loglist.currentlog,rslt);
  1170.         if loglist.log[loglist.currentlog].records > 0 then
  1171.           begin
  1172.             if precess(recnum, y_pos) then
  1173.               get_log(logbuf,last_log_data,recdata.recptr[recnum]);
  1174.           end
  1175.         else clear_log(last_log_data);
  1176.         close(logbuf);
  1177.       end;
  1178.     if last_log > 0 then { there is a log to alternate to }
  1179.       begin
  1180.         i:=last_log;
  1181.         last_log:=loglist.currentlog;
  1182.         loglist.currentlog:=i;
  1183.         put_loglist(loglist);
  1184.         do_unmark(FALSE);
  1185.       end;
  1186.     status_window;
  1187.     bottom_window;
  1188.     new_log(loglist.currentlog,rslt);
  1189.     x_pos:=1; y_pos:=1;
  1190.     gotoxy(x_pos,y_pos);
  1191.     show_log(rec,TRUE,TRUE);
  1192.   end;
  1193.  
  1194.   procedure update_time_status;
  1195.   var the_date:string;
  1196.       the_time:string;
  1197.   begin
  1198.     x_pos:=wherex; y_pos:=wherey;
  1199.     the_date:=mon_str + '/' + day_str + '/' + year_str;
  1200.     the_time:=copy(time_str,1,2) + ':' + copy(time_str,3,2) + ':' +
  1201.               copy(time_str,5,2);
  1202.     window(1,25,80,25);
  1203.     gotoxy(62,1);
  1204.     writea(BLACK,BACKGROUND);
  1205.     writea(CYAN, FOREGROUND);
  1206.     write(output,the_date,'  ', the_time);
  1207.     bottom_window;
  1208.   end;
  1209.  
  1210.   procedure do_journal;
  1211.   var ch:char;
  1212.       new:integer;
  1213.       found:boolean;
  1214.  
  1215.     procedure clr_prompt;
  1216.     begin
  1217.       gotoxy(1,2); clreol;
  1218.     end;
  1219.  
  1220.     procedure do_select(s:string; var new:integer; var found:boolean);
  1221.     var dummy1,dummy2:boolean;
  1222.         i, j, code, cmd:integer;
  1223.         ch:char;
  1224.         t,t1,t2:string;
  1225.     begin
  1226.       repeat
  1227.         clr_prompt;
  1228.         t2:='Enter log name or number ' + s + ' (Enter for none):';
  1229.         write(output,t2);
  1230.         t:='';
  1231.         editfield(length(t2) + 1,1,6,FALSE,dummy1,dummy2,t);
  1232.         t:=upcasestr(t);
  1233.  
  1234.         { search for duplicate }
  1235.         found:=FALSE;
  1236.         i:=0;
  1237.         while (i < MAXLOGS) and not found do
  1238.           begin
  1239.             inc(i);
  1240.             with loglist.log[i] do if t = logname then found:=TRUE;
  1241.           end;
  1242.  
  1243.         if not found then {see if they entered the log # instead of the name}
  1244.           begin
  1245.             t2:='';
  1246.             for i:=1 to length(t) do
  1247.               if (t[i] in ['0'..'9']) then t2:=t2 + t[i];
  1248.             val(t2, cmd, code);
  1249.             if code = 0 then
  1250.               begin
  1251.                 i:=0; j:=0;
  1252.                 while (j < cmd) and (i < MAXLOGS) do
  1253.                   begin
  1254.                     inc(i);
  1255.                     inc(j);
  1256.                     while (i < MAXLOGS) and (loglist.log[i].logname = '') do
  1257.                        inc(i);
  1258.                   end;
  1259.                 found:=loglist.log[i].logname <> '';
  1260.               end;
  1261.           end;
  1262.  
  1263.         if not found and (t[1] <> ' ') then
  1264.           begin
  1265.             clr_prompt;
  1266.             write(output,'Log not found <SPACE> to continue:');
  1267.             ch:=fetch;
  1268.             clr_prompt;
  1269.           end;
  1270.       until found or (t[1] = ' ');
  1271.       if not found then i:=loglist.currentlog;
  1272.       new:=i;
  1273.       clr_prompt;
  1274.     end;
  1275.  
  1276.     procedure do_create;
  1277.     var i:integer;
  1278.         s:short_str;
  1279.         dummy1,dummy2,found:boolean;
  1280.         ch:char;
  1281.     begin
  1282.       s:='';
  1283.       repeat
  1284.         clr_prompt;
  1285.         write('Enter new log name: ');
  1286.         editfield(22,1,6,FALSE,dummy1,dummy2,s);
  1287.         s:=upcasestr(s);
  1288.  
  1289.         { search for duplicate }
  1290.         found:=FALSE;
  1291.         for i:=1 to MAXLOGS do
  1292.           if s = upcasestr(loglist.log[i].logname) then found:=TRUE;
  1293.         if found then
  1294.           begin
  1295.             clr_prompt;
  1296.             write(output,s,': Duplicate log name <SPACE> to continue:');
  1297.             ch:=fetch;
  1298.             clr_prompt;
  1299.           end;
  1300.       until not found;
  1301.  
  1302.       { add name if not full }
  1303.       i:=0;
  1304.       while (i < MAXLOGS) and not found do
  1305.         begin
  1306.           i:=i + 1;
  1307.           if loglist.log[i].logname = '' then
  1308.             begin
  1309.               found:=TRUE;
  1310.               with loglist.log[i] do
  1311.                 begin
  1312.                   logname:=s;
  1313.                   records:=0;
  1314.                   rec:=1;
  1315.                 end;
  1316.               inc(loglist.logcount);
  1317.               put_loglist(loglist);
  1318.             end;
  1319.         end;
  1320.         if not found then
  1321.           begin
  1322.             clr_prompt;
  1323.             write(output,'Maximum number of logs exist <SPACE> to cont:');
  1324.             ch:=fetch;
  1325.             clr_prompt;
  1326.           end;
  1327.     end;
  1328.  
  1329.     procedure do_import;
  1330.     const db_name1 = 'SWSKED';
  1331.  
  1332.       procedure import(s:string);
  1333.       var found:boolean;
  1334.           rslt,i,j:integer;
  1335.           end_found:boolean;
  1336.  
  1337.         procedure move_db(logcnt:integer; var rslt:integer);
  1338.         var f:file;
  1339.             ch:char;
  1340.             i:integer;
  1341.             logdat:logtype;
  1342.             
  1343.           function read_file(chars:integer):string;
  1344.           var buf:array[1..255] of char;
  1345.               s:string;
  1346.               i:integer;
  1347.           begin
  1348.             rslt:=ioresult;
  1349.             s:='';
  1350.             if rslt <> 0 then read_file:=' '
  1351.             else
  1352.               begin
  1353.                 blockread(f,buf,chars);
  1354.                 for i:=1 to chars do s:=s + upcase(buf[i]);
  1355.                 read_file:=s;
  1356.               end;
  1357.           end;
  1358.  
  1359.           procedure strip_header;
  1360.           var buf:array[1..610] of char;
  1361.           begin
  1362.             { strip off first 610 characters and discard }
  1363.             blockread(f,buf,610);
  1364.             rslt:=ioresult;
  1365.           end;
  1366.  
  1367.           procedure get_entry(logcnt:integer);
  1368.           var logdat: logtype;
  1369.               freqs:array[1..10] of real;
  1370.               comments:array[1..10] of string[COMMENTLEN];
  1371.               i:integer;
  1372.  
  1373.             procedure get_location;
  1374.             var s:string;
  1375.                 i:integer;
  1376.                 test:boolean;
  1377.  
  1378.               function str_compare(s1,s2:string):boolean;
  1379.               var i:integer;
  1380.                   match:boolean;
  1381.               begin
  1382.                 match:=length(s1) = length(s2);
  1383.                 if match then for i:=1 to length(s1) do
  1384.                   if match then match:= s1[i] = s2[i];
  1385.                 str_compare:=match;
  1386.               end;
  1387.  
  1388.             begin
  1389.               s:=read_file(20);
  1390.               end_found:= pos(chr(26),s) <> 0;
  1391.               while length(s) < LOCATIONLEN do s:=s + ' ';
  1392.               logdat.location:=s;
  1393.             end;
  1394.  
  1395.             procedure get_station_id;
  1396.             var s:string;
  1397.             begin
  1398.               s:=read_file(24);
  1399.               while length(s) < CALLSIGNLEN do s:=s + ' ';
  1400.               logdat.callsign:=s;
  1401.             end;
  1402.  
  1403.             procedure get_start_time;
  1404.             begin
  1405.               logdat.begin_time:=read_file(4);
  1406.             end;
  1407.  
  1408.             procedure get_end_time;
  1409.             begin
  1410.               logdat.end_time:=read_file(4);
  1411.             end;
  1412.  
  1413.             function  get_freq:real;
  1414.             var freq:real;
  1415.                 i:integer;
  1416.                 s:string;
  1417.             begin
  1418.               freq:=0.0;
  1419.               s:=read_file(5);
  1420.               for i:=1 to 5 do
  1421.                 begin
  1422.                   if (s[i] in ['0'..'9'])
  1423.                      then freq:=freq * 10 + (ord(s[i]) - ord('0'));
  1424.                 end;
  1425.               get_freq:=freq;
  1426.             end;
  1427.  
  1428.             procedure get_comment;
  1429.             var s:string;
  1430.                 i:integer;
  1431.                 ch:char;
  1432.  
  1433.               procedure parse_comment(var s:string);
  1434.               var num1,num2,i,j:integer;
  1435.                   ch,separator:char;
  1436.                   s1,cmd:string;
  1437.                   found:boolean;
  1438.  
  1439.                 procedure get_num(var s:string; var num:integer);
  1440.                 var i:integer;
  1441.                     found:boolean;
  1442.                 begin
  1443.                   num:=0;
  1444.                   found:=FALSE;
  1445.                   while not found do
  1446.                     begin
  1447.                       num:=num * 10 + ord(s[1]) - ord('0');
  1448.                       delete(s,1,1);
  1449.                       found:=(s = '') or not (s[1] in ['0'..'9']);
  1450.                     end;
  1451.                 end;
  1452.  
  1453.                 procedure get_next_comment(var str:string);
  1454.                 var i:integer;
  1455.                 begin
  1456.                   i:=pos('#',s) - 1;
  1457.                   if i<=0 then i:=length(s);
  1458.                   str:=copy(s,1,i);
  1459.                   delete(s,1,i);
  1460.                 end;
  1461.  
  1462.                 procedure do_range; { case: #n-m }
  1463.                 var i:integer;
  1464.                     str:string;
  1465.                 begin
  1466.                   get_next_comment(str);
  1467.                   for i:=num1 to num2 do comments[i]:=comments[i] + str;
  1468.                   { handle case #m-n,o,... }
  1469.                   if cmd <> '' then while cmd[1] = ',' do
  1470.                     begin
  1471.                       delete(cmd,1,1);
  1472.                       get_num(cmd,num1);
  1473.                       comments[num1]:=comments[num1] + str;
  1474.                     end;
  1475.                 end;
  1476.  
  1477.                 procedure do_list; { case: #n,o,p...}
  1478.                 var i:integer;
  1479.                     str:string;
  1480.                 begin
  1481.                   get_next_comment(str);
  1482.                   comments[num1]:=comments[num1] + str;
  1483.                   comments[num2]:=comments[num2] + str;
  1484.                   if cmd <> '' then while cmd[1] = ',' do
  1485.                     begin
  1486.                       delete(cmd,1,1);
  1487.                       get_num(cmd,num1);
  1488.                       comments[num1]:=comments[num1] + str;
  1489.                     end;
  1490.                 end;
  1491.  
  1492.                 procedure do_entry; { case: #n }
  1493.                 var str:string;
  1494.                 begin
  1495.                   get_next_comment(str);
  1496.                   comments[num1]:=comments[num1] + str;
  1497.                 end;
  1498.  
  1499.                 procedure do_both; { case: #n&m }
  1500.                 var i:integer;
  1501.                     str:string;
  1502.                 begin
  1503.                   get_next_comment(str);
  1504.                   comments[num1]:=comments[num1] + str;
  1505.                   comments[num2]:=comments[num2] + str;
  1506.                   if cmd <> '' then while cmd[1] = '&' do
  1507.                     begin
  1508.                       delete(cmd,1,1);
  1509.                       get_num(cmd,num1);
  1510.                       comments[num1]:=comments[num1] + str;
  1511.                     end;
  1512.                 end;
  1513.  
  1514.               begin { parse comment }
  1515.                 { check for comment unique to entries }
  1516.                 i:=pos('#',s);
  1517.                 if i = 0 then i:=length(s) + 1;
  1518.                 { copy message up to command to each comment }
  1519.                 s1:=copy(s,1,i - 1);
  1520.                 for j:=1 to 10 do comments[j]:=comments[j] + s1;
  1521.  
  1522.                 { get comments unique to entry eg #4&5 }
  1523.                 cmd:='';
  1524.                 j:=i + 1;
  1525.                 found:=FALSE;
  1526.                 while (j < length(s)) and not found do
  1527.                   begin
  1528.                     found:=s[j] in [' ','#'];
  1529.                     if not found then
  1530.                       begin
  1531.                         cmd:=cmd + s[j];
  1532.                         inc(j);
  1533.                       end;
  1534.                   end;
  1535.                 delete(s,1,j - 1);
  1536.  
  1537.                 { decode unique comments and assign }
  1538.                 {   known formats: #n, #n&m, #n,m,...,#n-m }
  1539.                 get_num(cmd,num1);
  1540.                 if cmd <> '' then
  1541.                   begin
  1542.                     separator:=cmd[1];
  1543.                     delete(cmd,1,1);
  1544.                     get_num(cmd,num2);
  1545.                   end;
  1546.                 case separator of
  1547.                   '-': do_range;
  1548.                   '&': do_both;
  1549.                   ',': do_list;
  1550.                   else do_entry;
  1551.                 end;
  1552.               end;
  1553.  
  1554.             begin { get_comment }
  1555.               for i:=1 to 10 do comments[i]:='';
  1556.               s:='Target:' + read_file(40);
  1557.               { parse comments for individual entries }
  1558.               while length(s) > 0 do parse_comment(s);
  1559.               for i:=1 to 10 do while length(comments[i]) < COMMENTLEN do
  1560.                  comments[i]:=comments[i] + ' ';
  1561.             end;
  1562.  
  1563.             procedure get_date;
  1564.             var s:string;
  1565.             begin
  1566.               s:=read_file(2); { discard decade ie 19 }
  1567.               logdat.date:=read_file(6);
  1568.             end;
  1569.  
  1570.             procedure skip;
  1571.             var dummy:string;
  1572.             begin
  1573.               dummy:=read_file(9);
  1574.             end;
  1575.  
  1576.           begin { get_entry }
  1577.             { set variables that won't change for the duration }
  1578.             with logdat do
  1579.               begin
  1580.                 agc:=FAST;
  1581.                 mode:=USB;
  1582.                 bandwidth:=INTER;
  1583.               end;
  1584.             get_location;
  1585.             if end_found then exit;
  1586.             get_station_id;
  1587.             get_start_time;
  1588.             get_end_time;
  1589.             for i:=1 to 10 do freqs[i]:=get_freq;
  1590.             get_comment;
  1591.             get_date;
  1592.             skip;
  1593.             for i:=1 to 10 do
  1594.               begin
  1595.                 if freqs[i] <> 0.0 then
  1596.                   begin
  1597.                     with loglist.log[logcnt] do
  1598.                       begin
  1599.                         inc(records);
  1600.                         write(output,'.');
  1601.                         if records < MAXREC then
  1602.                           begin
  1603.                             logdat.comment:=comments[i];
  1604.                             logdat.frequency:=freqs[i];
  1605.                             logdat.attenuator:=NO;
  1606.                             put_log(logbuf,logdat,records);
  1607.                           end;
  1608.                       end;
  1609.                   end;
  1610.               end;
  1611.           end;
  1612.  
  1613.         begin { move_db }
  1614.           assign(f,PATH+S+'.DBF');
  1615.           reset(f,1);
  1616.           rslt:=ioresult;
  1617.           if rslt <> 0 then
  1618.             begin
  1619.               writeln(output,
  1620.                    'Must have ',PATH+S+'.DBF in directory to import');
  1621.               hndlerr(TRUE,ch,rslt);
  1622.               exit;
  1623.             end;
  1624.           strip_header;
  1625.           home;
  1626.           write(output,'Reading / parsing database');
  1627.           end_found:=false;
  1628.           while (rslt = 0) and not end_found do get_entry(logcnt);
  1629.           close(f);
  1630.           records:=loglist.log[loglist.currentlog].records;
  1631.           for i:=1 to MAXREC do
  1632.             begin
  1633.               recdata.recptr[i]:=i;
  1634.               recdata.recstat[i]:=SHOW;
  1635.             end;
  1636.           put_recdata(loglist.currentlog,recdata);
  1637.           put_loglist(loglist);
  1638.           rslt:=0;
  1639.         end;
  1640.  
  1641.         procedure eliminate_dups(lognum:integer);
  1642.         { collapse entries with time overlap }
  1643.         var rec1ptr,i,j,t,rslt:integer;
  1644.             logdata1,logdata2:logtype;
  1645.         begin
  1646.           home;
  1647.           write(output,'Crunching duplicate entries');
  1648.           get_log(logbuf,logdata1,recdata.recptr[1]);
  1649.           rec1ptr:=1;
  1650.           i:=2;
  1651.           while (i < loglist.log[lognum].records) do
  1652.             begin
  1653.               if recdata.recstat[recdata.recptr[i]] = DELETED then exit;
  1654.               get_log(logbuf,logdata2,recdata.recptr[i]);
  1655.               write(output,'.');
  1656.               if (logdata2.frequency  = logdata1.frequency) and
  1657.                  (logdata2.begin_time = logdata1.end_time)  and
  1658.                  (logdata2.comment    = logdata1.comment)   and
  1659.                  (logdata2.location   = logdata1.location)  and
  1660.                  (logdata2.callsign   = logdata1.callsign) then
  1661.                 begin
  1662.                   logdata1.end_time:=logdata2.end_time;
  1663.                   put_log(logbuf,logdata1,recdata.recptr[rec1ptr]);
  1664.                   t:=recdata.recptr[i];
  1665.                   recdata.recstat[t]:=DELETED;
  1666.                   for j:=i to records - 1 do with recdata do
  1667.                      recptr[j]:=recptr[j + 1];
  1668.                   recdata.recptr[records]:=t;
  1669.                 end
  1670.               else { no match }
  1671.                 begin
  1672.                   logdata1:=logdata2;
  1673.                   rec1ptr:=i;
  1674.                   inc(i);
  1675.                 end;
  1676.             end;
  1677.         end;
  1678.  
  1679.       begin { import }
  1680.         found:=FALSE;
  1681.         i:=0;
  1682.         while not found and (i < MAXLOGS) do
  1683.           begin
  1684.             inc(i);
  1685.             if s = upcasestr(loglist.log[i].logname) then found:=TRUE;
  1686.           end;
  1687.         if found then
  1688.           begin
  1689.             with loglist.log[i] do
  1690.                begin
  1691.                  logname:=s;
  1692.                  records:=0;
  1693.                  rec:=1;
  1694.                end;
  1695.           end
  1696.         else { add name if not full }
  1697.           begin
  1698.             i:=0;
  1699.             while (i < MAXLOGS) and not found do
  1700.               begin
  1701.                 i:=i + 1;
  1702.                 if loglist.log[i].logname = '' then
  1703.                   begin
  1704.                     found:=TRUE;
  1705.                     inc(loglist.logcount);
  1706.                     put_loglist(loglist);
  1707.                   end;
  1708.               end;
  1709.             if not found then
  1710.               begin
  1711.                 clr_prompt;
  1712.                 write(output,'Maximum number of logs exist <SPACE> to cont:');
  1713.                 ch:=fetch;
  1714.                 clr_prompt;
  1715.                 exit;
  1716.               end;
  1717.             with loglist.log[i] do
  1718.                begin
  1719.                  logname:=s;
  1720.                  records:=0;
  1721.                  rec:=1;
  1722.                end;
  1723.           end;
  1724.         loglist.currentlog:=i;
  1725.         open_log(logbuf,i,rslt);
  1726.         move_db(i,rslt);
  1727.         if rslt = 0 then
  1728.           begin
  1729.             home;
  1730.             do_sort(TRUE);
  1731.             eliminate_dups(i);
  1732.             put_recdata(loglist.currentlog,recdata);
  1733.           end;
  1734.         close(logbuf);
  1735.       end;
  1736.  
  1737.     begin
  1738.       import(db_name1);
  1739.     end;
  1740.  
  1741.     procedure do_export;
  1742.     var i:integer;
  1743.         dummy:boolean;
  1744.         logdata:logtype;
  1745.         dbfbuf:text;
  1746.  
  1747.       procedure open_dbf(s:string);
  1748.       var ch:char;
  1749.       begin
  1750.         assign(dbfbuf,PATH + s + '.DBF');
  1751.         repeat
  1752.           rewrite(dbfbuf);
  1753.           rslt:=ioresult;
  1754.           hndlerr(FALSE,ch,rslt);
  1755.         until (rslt = 0) or (ch = KEYINFO.ESCKEY);
  1756.       end;
  1757.  
  1758.       procedure write_dbf_header;
  1759.       const VERSION_NUM = 03;
  1760.       var s:string;
  1761.           yr,mo,dy,dyofweek:word;
  1762.           rec_lsb, rec_msb:byte;
  1763.       begin
  1764.         { byte 0: write version number }
  1765.         write(dbfbuf,chr(VERSION_NUM));
  1766.  
  1767.         { byte 1-3: write update date YY, MM, DD }
  1768.         getdate(yr,mo,dy,dyofweek);
  1769.         yr:=yr mod 100;
  1770.         write(dbfbuf,chr(yr) + chr(mo) + chr(dy));
  1771.  
  1772.         { byte 4-7: write number of records LSB--MSB }
  1773.         rec_msb:=records div 256;
  1774.         rec_lsb:=records mod 256;
  1775.         write(dbfbuf,chr(rec_lsb),chr(rec_msb),chr(0),chr(0));
  1776.  
  1777.         { byte 8-9: length of header structure }
  1778.  
  1779.         { byte 10-11: length of the record }
  1780.  
  1781.         { byte 12-31: reserved; write 00 }
  1782.  
  1783.         { byte 32-n: field descriptors - one per field }
  1784.  
  1785.            { byte 0-10: field name }
  1786.            { byte 11: field type - "C" = character
  1787.                                    "N" = numeric (not used)
  1788.                                    "L" = logical (not used)
  1789.                                    "M" = memo (not used)
  1790.                                    "D" = date (YYYYMMDD)}
  1791.            { byte 12-15: field data address }
  1792.            { byte 16: field length }
  1793.            { byte 17: field decimal count }
  1794.            { byte 18-21: reserved; write 00 }
  1795.       end;
  1796.  
  1797.       procedure write_dbf_record(logdata:logtype);
  1798.       begin
  1799.         with logdata do
  1800.           begin
  1801.           end;
  1802.       end;
  1803.  
  1804.     begin
  1805.       i:=0;
  1806.       with loglist do
  1807.         begin
  1808.           open_log(logbuf,currentlog,rslt);
  1809.           open_dbf(log[currentlog].logname);
  1810.         end;
  1811.       write_dbf_header;
  1812.       while (i < records) do
  1813.         begin
  1814.           dummy:=precess(i,1);
  1815.           get_log(logbuf,logdata,recdata.recptr[i]);
  1816.           write_dbf_record(logdata);
  1817.         end;
  1818.       close(logbuf);
  1819.       close(dbfbuf);
  1820.     end;
  1821.  
  1822.     procedure do_delete;
  1823.     var i:integer;
  1824.         s1:short_str;
  1825.         dummy1,dummy2,found:boolean;
  1826.         ch:char;
  1827.         f:file;
  1828.     begin
  1829.       do_select('to DELETE',i,found);
  1830.       if found then
  1831.         begin
  1832.           clr_prompt;
  1833.           write(output,'DELETE ',upcasestr(loglist.log[i].logname),'?');
  1834.           ch:=upcase(fetch);
  1835.           clr_prompt;
  1836.           if ch = 'Y' then
  1837.             begin
  1838.               loglist.log[i].logname:='';
  1839.               loglist.log[i].records:=0;
  1840.               loglist.log[i].rec:=0;
  1841.               loglist.logcount:=loglist.logcount - 1;
  1842.               if loglist.currentlog = i then loglist.currentlog:=0;
  1843.               if last_log = i then last_log:=0;
  1844.               put_loglist(loglist);
  1845.               str(i,s1);
  1846.               if length(s1) = 1 then s1:='0' + s1;
  1847.               s1:=s1 + '.DAT';
  1848.               assign(f,PATH + RECDATAFILE + s1);
  1849.               erase(f);
  1850.               assign(f,PATH + LOGFILE + s1);
  1851.               erase(f);
  1852.             end;
  1853.         end;
  1854.     end;
  1855.  
  1856.     procedure display_logs;
  1857.     var i,j,k,deletions:integer;
  1858.         t:string;
  1859.         recdata:recdatatype;
  1860.     begin
  1861.       gotoxy(1,4);
  1862.       call_crt(ERASEOS);
  1863.       j:=0;
  1864.       for i:=1 to MAXLOGS do
  1865.         begin
  1866.           t:=loglist.log[i].logname;
  1867.           if t <> '' then { display it }
  1868.             begin
  1869.               inc(j);
  1870.               deletions:=0;
  1871.               get_recdata(i,recdata);
  1872.               for k:=1 to loglist.log[i].records do
  1873.                 if recdata.recstat[k] = DELETED then inc(deletions);
  1874.               writeln(output,j:3,'  ',t,' ',loglist.log[i].records
  1875.                                   - deletions);
  1876.             end;
  1877.         end;
  1878.     end;
  1879.  
  1880.     procedure move_record(marked, move:boolean; dest, from:byte);
  1881.     var x_pos,y_pos:integer;
  1882.       t,recnum:integer;
  1883.       ch:char;
  1884.       i,j:integer;
  1885.       dummy:boolean;
  1886.       logdata:logtype;
  1887.       to_recdata,from_recdata:recdatatype;
  1888.       found:boolean;
  1889.       from_buf,to_buf:file;
  1890.  
  1891.       function get_logentry(i:integer;var logdata:logtype):boolean;
  1892.       var found:boolean;
  1893.           j,k,l:integer;
  1894.       begin
  1895.         found:=TRUE;
  1896.         j:=from_recdata.recptr[i];
  1897.         if marked then found:=(i >=min_mark) and (i <=max_mark);
  1898.         found:=found and (from_recdata.recstat[j] = SHOW);
  1899.         if found then
  1900.           begin
  1901.             get_log(from_buf,logdata,j);
  1902.             if move then { delete old entry }
  1903.                 from_recdata.recstat[j]:=DELETED;
  1904.           end;
  1905.         get_logentry:=found;
  1906.       end;
  1907.  
  1908.       procedure put_logentry(var i:integer; logdata:logtype);
  1909.       var j:integer;
  1910.       begin
  1911.         while (i < loglist.log[dest].records)
  1912.           and (to_recdata.recstat[to_recdata.recptr[i]] <> DELETED)
  1913.                   do inc(i);
  1914.         if (i >= loglist.log[dest].records)
  1915.            and (to_recdata.recstat[to_recdata.recptr[i]] <> DELETED) then
  1916.         { insert new entry here }
  1917.           begin
  1918.             inc(loglist.log[dest].records);
  1919.             i:=loglist.log[dest].records;
  1920.             to_recdata.recptr[i]:=i;
  1921.             if recnum = 0 then recnum:=1;
  1922.           end;
  1923.         t:=to_recdata.recptr[i];
  1924.         for j:=i downto recnum + 1 do with to_recdata do
  1925.           recptr[j]:=recptr[j - 1];
  1926.         to_recdata.recptr[recnum]:=t;
  1927.         to_recdata.recstat[t]:=SHOW;
  1928.         put_log(to_buf,logdata,to_recdata.recptr[recnum]);
  1929.         inc(recnum);
  1930.       end;
  1931.  
  1932.       procedure push_delete;
  1933.       { push deleted records to the end of the chain }
  1934.       var i,j,k,cnt,last:integer;
  1935.       begin
  1936.         last:=loglist.log[from].records;
  1937.         i:=1; cnt:=1;
  1938.         while (cnt < last) do
  1939.         { move deletions to the top of the stack; "cnt" limits iterations }
  1940.           begin
  1941.             j:=from_recdata.recptr[i];
  1942.             if from_recdata.recstat[j] = DELETED then
  1943.               begin
  1944.                 for k:=i to last - 1 do
  1945.                   from_recdata.recptr[k]:=from_recdata.recptr[k + 1];
  1946.                 from_recdata.recptr[last]:=j;
  1947.               end
  1948.             else inc(i);
  1949.             inc(cnt);
  1950.           end;
  1951.       end;
  1952.  
  1953.     begin {move_record }
  1954.       recnum:=loglist.log[dest].rec;
  1955.       get_recdata(from,from_recdata);
  1956.       get_recdata(dest,to_recdata);
  1957.       open_log(from_buf,from,rslt); if rslt > 0 then exit;
  1958.       open_log(to_buf,dest,rslt);   if rslt > 0 then exit;
  1959.       j:=1;
  1960.       for i:=1 to loglist.log[from].records do
  1961.         begin
  1962.           found:=get_logentry(i,logdata);
  1963.           if found then put_logentry(j,logdata);
  1964.         end;
  1965.       if move then push_delete;
  1966.       close(to_buf);
  1967.       close(from_buf);
  1968.       put_recdata(dest,to_recdata);
  1969.       put_recdata(from,from_recdata);
  1970.       put_loglist(loglist);
  1971.     end;
  1972.  
  1973.     procedure do_the_write;
  1974.     var dest:integer;
  1975.         found:boolean;
  1976.     begin
  1977.       do_select('to write to',dest, found);
  1978.       if found then move_record(TRUE,FALSE,dest,loglist.currentlog);
  1979.     end;
  1980.  
  1981.     procedure do_move;
  1982.     var dest:integer;
  1983.         found:boolean;
  1984.     begin
  1985.       do_select('to move to',dest, found);
  1986.       if found then
  1987.         begin
  1988.           move_record(TRUE,TRUE,dest,loglist.currentlog);
  1989.           do_unmark(FALSE);
  1990.         end;
  1991.     end;
  1992.  
  1993.     procedure do_print;
  1994.  
  1995.     const LINESPERPAGE = 60;
  1996.  
  1997.     var pbuf:text;
  1998.         i,cnt:integer;
  1999.         dummy:boolean;
  2000.         logdata:logtype;
  2001.         s:short_str;
  2002.         s1:string;
  2003.         logbuf:file;
  2004.         rslt:integer;
  2005.  
  2006.       procedure printhdr;
  2007.       begin
  2008.         write(pbuf,'Num   Date  Strt End  Freq     '+
  2009.                           'Station ID          Location');
  2010.         writeln(pbuf,'Comment':22,'Md':35,' BW');
  2011.         cnt:=1;
  2012.       end;
  2013.  
  2014.     begin
  2015.       assign(pbuf,'LPT1');
  2016.       rewrite(pbuf);
  2017.       write(pbuf,chr(27),'g'); { compressed mode }
  2018.       printhdr;
  2019.       i:=0;
  2020.       open_log(logbuf,loglist.currentlog,rslt);
  2021.       while (i < records) do
  2022.         begin
  2023.           dummy:=precess(i,1);
  2024.           get_log(logbuf,logdata,recdata.recptr[i]);
  2025.           if (i >= min_mark) and (i <= max_mark) then
  2026.             begin
  2027.               inc(cnt);
  2028.               if cnt > LINESPERPAGE then
  2029.                 begin
  2030.                   write(pbuf,chr(12)); { form feed }
  2031.                   printhdr;
  2032.                 end;
  2033.               with logdata do
  2034.                 begin
  2035.                   write(pbuf,i:4,date:DATELEN + 1,begin_time:TIMELEN + 1);
  2036.                   write(pbuf,end_time:TIMELEN + 1);
  2037.                   write(pbuf,frequency:9:2,callsign:CALLSIGNLEN + 1);
  2038.                   s1:=copy(location,1,22);
  2039.                   while length(s1) < 22 do s1:=s1 + ' ';
  2040.                   write(pbuf,s1:23);
  2041.                   s1:=copy(comment,1,39);
  2042.                   while length(s1) < 39 do s1:=s1 + ' ';
  2043.                   write(pbuf,s1:40);
  2044.                   case mode of
  2045.                     RTTY:     s:='RT';
  2046.                     CW:       s:='CW';
  2047.                     USB:      s:='UB';
  2048.                     LSB:      s:='LB';
  2049.                     AM:       s:='AM';
  2050.                     FM:       s:='FM';
  2051.                     FAX:      s:='FX';
  2052.                     ECSS_USB: s:='Eu';
  2053.                     ECSS_LSB: s:='El';
  2054.                   end;
  2055.                   write(pbuf,s:3);
  2056.                   case bandwidth of
  2057.                     NARR:  s:='NR';
  2058.                     INTER: s:='IN';
  2059.                     WIDE:  s:='WD';
  2060.                     AUX:   s:='AX';
  2061.                   end;
  2062.                   writeln(pbuf,s:3);
  2063.                 end;
  2064.             end;
  2065.         end;
  2066.       close(pbuf);
  2067.       close(logbuf);
  2068.     end;
  2069.  
  2070.   begin
  2071.     sync_loglist;
  2072.     close(logbuf);
  2073.     repeat
  2074.       write_prompt('Journal: '+
  2075.    'S(elect, C(reate, D(el, I(mport, W(rite, M(ove, P(rint, Q(uit');
  2076.       bottom_window;
  2077.       home;
  2078.       display_logs;
  2079.       repeat
  2080.         { check for timer tick }
  2081.         time_date_stamp(mon_str,day_str,year_str,time_str,FALSE);
  2082.         if time_str <> old_time_str then
  2083.           begin
  2084.             update_time_status;
  2085.             old_time_str:=time_str;
  2086.           end;
  2087.       until keypressed;
  2088.       ch:=upcase(fetch);
  2089.       case ch of
  2090.         'S','Q':begin
  2091.                   do_select('to switch to', new, found);
  2092.                   last_log:=new;
  2093.                   if loglist.currentlog = last_log then last_log:=0;
  2094.                   put_loglist(loglist);
  2095.                   cmd_prompt(prompt_num);
  2096.                   do_alternate;
  2097.                   exit;
  2098.                 end;
  2099.         'C': do_create;
  2100.         'D': do_delete;
  2101.         'W': do_the_write;
  2102.         'M': do_move;
  2103.         'P': do_print;
  2104.         'I': do_import;
  2105.         'E': {do_export};
  2106.       end;
  2107.     until (ch = 'Q');
  2108.   end;
  2109.  
  2110.   procedure call_do_help;
  2111.   begin
  2112.     do_help;
  2113.     show_log(rec,TRUE,TRUE);
  2114.   end;
  2115.  
  2116. begin { nrd }
  2117.   graph_init;
  2118.   old_time_str:='';
  2119.   old_time_stamp:=0;
  2120.   last_log:=0;
  2121.   enable_s_meter:=FALSE;
  2122.   init_com;
  2123.   if has_map then
  2124.     begin
  2125.       remote_on;  { get receiver status to see if map is on }
  2126.       remote_off(0);
  2127.       map:=receiverstat.mode = AM;  { assume MAP in use if radio in AM }
  2128.     end
  2129.   else map:=FALSE;
  2130.   prompt_num:=PAGE1;
  2131.   get_loglist(loglist);
  2132.   new_log(loglist.currentlog,rslt);
  2133.   init_crt;
  2134.   x_pos:=1; y_pos:=1;
  2135.   gotoxy(x_pos,y_pos);
  2136.   do_unmark(TRUE);
  2137.  
  2138.   { init old receiver status to current radio settings }
  2139.   oldstat:=receiverstat;
  2140.   if radio_type = 535 then
  2141.     begin
  2142.       toggle_remote; { get radio status; dial changes will be cont sent }
  2143.       show_receiver;
  2144.     end;
  2145.   repeat
  2146.     repeat
  2147.       if (radio_type = 535) and async_buffer_check(ch) then
  2148.         begin
  2149.           check_status(s); { they changed dial }
  2150.           show_receiver;
  2151.         end;
  2152.  
  2153.       { check for timer tick }
  2154.       time_date_stamp(mon_str,day_str,year_str,time_str,FALSE);
  2155.       if time_str <> old_time_str then
  2156.         begin
  2157.           if enable_s_meter then timed_s_meter;
  2158.           update_time_status;
  2159.           old_time_str:=time_str;
  2160.         end;
  2161.  
  2162.       if update_receiver_display then
  2163.         begin
  2164.           if radio_type = 525 then
  2165.             begin
  2166.               remote_on;
  2167.               show_receiver;
  2168.               remote_off(REMOTE_DLY);
  2169.             end
  2170.           else
  2171.             begin
  2172.               toggle_remote;
  2173.               show_receiver;
  2174.             end;
  2175.           update_receiver_display:=FALSE;
  2176.         end;
  2177.       until keypressed;
  2178.     ch:=upcase(fetch);
  2179.     case ch of
  2180.       '@':; { nop }
  2181.       '+':              inc_freq;
  2182.       '-':              dec_freq;
  2183.       '*':              find_freq;
  2184.       '/':              begin
  2185.                           if prompt_num = PAGE1 then prompt_num:=PAGE2
  2186.                                                 else prompt_num:=PAGE1;
  2187.                           cmd_prompt(prompt_num);
  2188.                           bottom_window;
  2189.                         end;
  2190.       'A':              begin
  2191.                           close(logbuf);
  2192.                           do_alternate;
  2193.                         end;
  2194.       'C':              do_confirm;
  2195.       'P':              do_page;
  2196.       'S':              do_sort(FALSE);
  2197.       'E':              do_edit;
  2198.       'G':              do_graph;
  2199.       'J':              do_journal;
  2200.       'D':              do_delete;
  2201.       'N':              do_undelete;
  2202.       'M':              do_mark;
  2203.       'U':              do_unmark(TRUE);
  2204.       'L':              do_log;
  2205.       'R':              begin
  2206.                           enable_s_meter:=not enable_s_meter;
  2207.                           if not enable_s_meter then
  2208.                             begin
  2209.                               top_window;
  2210.                               gotoxy(42,3);
  2211.                               write(output,'          ');
  2212.                               bottom_window;
  2213.                             end;
  2214.                         end;
  2215.       'T':              do_tune;
  2216.       'K':              if has_map then do_kiwa;
  2217.       'W':              do_write;
  2218.       '>':              inc_mode;
  2219.       '.':              inc_mode;
  2220.       '<':              dec_mode;
  2221.       ',':              dec_mode;
  2222.       ']':              inc_bandwidth;
  2223.       '[':              dec_bandwidth;
  2224.       'H':              begin
  2225.                           call_do_help;
  2226.                           status_window;
  2227.                         end;
  2228.       PAGEUP:           do_pageup(1);
  2229.       PAGEDOWN:         do_pagedown(1);
  2230.       UP:               do_up;
  2231.       DOWN:             do_down;
  2232.       RIGHTARROW:       do_right;
  2233.       LEFTARROW:        do_left;
  2234.       BACKTAB:          do_backtab;
  2235.       TAB:              do_tab;
  2236.       CTRLPAGEUP:       do_pageup(10);
  2237.       CTRLPAGEDN:       do_pagedown(10);
  2238.       HOMEKY:           do_home;
  2239.       ENDKY:            do_end;
  2240.       else update_receiver_display:=TRUE;
  2241.     end;
  2242.   until ch = 'Q';
  2243.   if radio_type = 535 then information_mode_off;
  2244.   sync_loglist;
  2245.   close(logbuf);
  2246.   window(1,1,80,25);
  2247.   home;
  2248.   gotoxy(1,8);
  2249.   writeln(output,'Send comments and suggestions to:');
  2250.   writeln(output);
  2251.   writeln(output,'    Tom Whiteside (512) 258-5924');
  2252.   writeln(output,'    11505 Oak View');
  2253.   writeln(output,'    Austin, TX 78759');
  2254. end.  { nrd }
  2255.